﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CoderJoe
{
    public abstract class ServiceBase
    {
        protected virtual IDisposable CreateServiceContext()
        {
            return null;
        }

        protected virtual void HandleServiceException(Exception ex)
        {
            throw ex;
        }

        protected TResult Invoke<TResult>(Func<TResult> func)
        {
            try
            {
                using (CreateServiceContext())
                {
                    return func();
                }
            }
            catch (Exception ex)
            {
                HandleServiceException(ex);
            }

            return default(TResult);
        }

        protected TResult Invoke<TArg,TResult>(Func<TArg, TResult> func, TArg arg)
        {
            return Invoke<TResult>(
                delegate()
                {
                    return func(arg);
                });
        }

        protected TResult Invoke<TArg1, TArg2, TResult>(Func<TArg1, TArg2, TResult> func, TArg1 arg1, TArg2 arg2)
        {
            return Invoke<TResult>(
                delegate()
                {
                    return func(arg1, arg2);
                });
        }

        protected TResult Invoke<TArg1, TArg2, TArg3, TResult>(Func<TArg1, TArg2, TArg3, TResult> func, TArg1 arg1, TArg2 arg2, TArg3 arg3)
        {
            return Invoke<TResult>(
                delegate()
                {
                    return func(arg1, arg2, arg3);
                });
        }

        protected TResult Invoke<TArg1, TArg2, TArg3, TArg4, TResult>(Func<TArg1, TArg2, TArg3, TArg4, TResult> func, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4)
        {
            return Invoke<TResult>(
                delegate()
                {
                    return func(arg1, arg2, arg3, arg4);
                });
        }

        protected void Invoke(Action method)
        {
            Invoke<object>(
                delegate()
                {
                    method();
                    return null;
                });
        }

        protected void Invoke<TArg>(Action<TArg> method, TArg arg)
        {
            Invoke(
                delegate()
                {
                    method(arg);
                });
        }

        protected void Invoke<TArg1, TArg2>(Action<TArg1, TArg2> method, TArg1 arg1, TArg2 arg2)
        {
            Invoke(
                delegate()
                {
                    method(arg1, arg2);
                });
        }

        protected void Invoke<TArg1, TArg2, TArg3>(Action<TArg1, TArg2, TArg3> method, TArg1 arg1, TArg2 arg2, TArg3 arg3)
        {
            Invoke(
                delegate()
                {
                    method(arg1, arg2, arg3);
                });
        }

        protected void Invoke<TArg1, TArg2, TArg3, TArg4>(Action<TArg1, TArg2, TArg3, TArg4> method, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4)
        {
            Invoke(
                delegate()
                {
                    method(arg1, arg2, arg3, arg4);
                });
        }
    }
}
